﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Configuration;

public partial class Clipboard : System.Web.UI.Page
{
	protected readonly int MAX_ENTRIES = int.Parse(ConfigurationSettings.AppSettings["clipboard.maxEntries"]);
	protected readonly int REFRESH_INTERVAL = int.Parse(ConfigurationSettings.AppSettings["clipboard.refreshInterval"]);
	
	protected string userName = HttpContext.Current.User.Identity.Name;

    protected void Page_Load(object sender, EventArgs e)
    {
		timer.Interval = REFRESH_INTERVAL;
		LoadContent();
    }

    protected void RefreshContent_Click(object sender, EventArgs e)
    {
		LoadContent();
	}

	protected void EmptyContent_Click(object sender, EventArgs e)
	{
		EmptyContent();
	}

	protected void EmptyContent()
	{
		try
		{
			IEnumerable<IClipboardContent> content = LoadClipboardContent();
			foreach (var entry in content)
			{
				File.Delete(entry.FileName);
				if (entry.ContentType == ClipboardContentType.File)
					File.Delete(Server.MapPath(((FileClipboardContent)entry).File));
				if (entry.ContentType == ClipboardContentType.Image)
					File.Delete(Server.MapPath(((ImageClipboardContent)entry).File));

			}
			LoadContent();
		}
		catch (Exception ex)
		{
			message.Text = ex.Message;
		}
	}

	protected void deleteButton_Click(object sender, EventArgs e)
	{
		StreamReader sr = null;
		try
		{
			LinkButton li = sender as LinkButton;
			if (li == null) return;

			string id = li.CommandArgument;

			IEnumerable<IClipboardContent> content = LoadClipboardContent();
			foreach (var entry in content)
			{
				sr = File.OpenText(entry.FileName);
				string fid = sr.ReadLine();
				sr.Close();
				if (id == fid)
				{
					File.Delete(entry.FileName);
					if (entry.ContentType == ClipboardContentType.File)
						File.Delete(Server.MapPath(((FileClipboardContent)entry).File));
					if (entry.ContentType == ClipboardContentType.Image)
						File.Delete(Server.MapPath(((ImageClipboardContent)entry).File));
					break;
				}
			}
			LoadContent();
		}
		catch (Exception ex)
		{
			message.Text = ex.Message;
		}
		finally
		{
			try { sr.Close(); }	catch { }
		}
	}

	protected void LoadContent()
	{
		message.Text = "";
        
		dataList.DataSource = LoadClipboardContent();
        dataList.DataBind();
		lastRefresh.Text = String.Format("Last refresh time: {0}", DateTime.Now.ToString());
        updatePanel.Update();
    }

    protected void uploadButton_Click(object sender, EventArgs e)
    {
        if (fileUpload.HasFile)
        {
            try
            {
                string path = String.Format("{0}/{1}", GetWorkingPath(),fileUpload.FileName);
                fileUpload.SaveAs(path);

				string ext = Path.GetExtension(path).ToLower().Replace(".","");
				if(ext == "jpg" || ext == "gif" || ext == "png")
					SaveClipboardContent(new ImageClipboardContent(String.Format("~/Clipboard/Files/{0}/{1}", userName, fileUpload.FileName)));
				else
					SaveClipboardContent(new FileClipboardContent(String.Format("~/Clipboard/Files/{0}/{1}", userName, fileUpload.FileName)));
            }
            catch(Exception ex)
            {
				message.Text = ex.Message; 
            }
        }
    }

    protected void sendButton_Click(object sender, EventArgs e)
    {
        SaveClipboardContent(new TextClipboardContent(text.Text));
        text.Text = "";
    }

    protected string GetWorkingPath()
    {
        string path = Server.MapPath(String.Format("~/Clipboard/Files/{0}",userName));
		Directory.CreateDirectory(path);

		return path;
    }

    protected void SaveClipboardContent(IClipboardContent content)
    {
		StreamWriter sw = null;
		try
		{
			string path = GetWorkingPath();
			string file = Path.Combine(path, String.Format("{0}_{1}.clipo", content.ContentType.ToString(), DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss")));

			// append a consecutive number in case the file already exists
			int index = 0; string newFile = file;
			while (File.Exists(newFile))
			{
				newFile = String.Format("{0}{1}", file, index++);
			}
			file = newFile;

			sw = File.CreateText(file);
			sw.WriteLine(content.Id);
			sw.Write(content.Content);
			sw.Flush();
		}
		catch (Exception ex)
		{
			message.Text = ex.Message;
		}
		finally
		{
			try { sw.Close(); } catch {}
		}
    }

    protected IEnumerable<IClipboardContent> LoadClipboardContent()
    {
        SortedList<DateTime, IClipboardContent> sl = new SortedList<DateTime, IClipboardContent>();
		StreamReader sr = null;

		try
		{
			string path = GetWorkingPath();
			DirectoryInfo di = new DirectoryInfo(path);
			if (di.Exists)
			{
				foreach (FileInfo fi in di.GetFiles("*.clipo"))
				{
					string[] parts = Path.ChangeExtension(fi.Name, null).Split('_');
					string fileContentType = parts[0];
					parts = parts[1].Split('T');
					string fileDateTime = String.Format("{0}T{1}", parts[0], parts[1].Replace("-", ":"));

					sr = fi.OpenText();
					string id = sr.ReadLine();
					string text = sr.ReadToEnd();
					sr.Close();

					IClipboardContent clipboardContent = ClipboardContent.ParseClipboardContent(fileContentType, text);
					if (clipboardContent == null) continue;

					clipboardContent.Id = id;
					clipboardContent.FileName = fi.FullName;
					clipboardContent.Date = DateTime.Parse(fileDateTime);
					sl.Add(clipboardContent.Date, clipboardContent);
				}
			}

			IEnumerable<IClipboardContent> result = sl.Values.Reverse();

			foreach(var entry in result.Skip(MAX_ENTRIES))
			{
				File.Delete(entry.FileName);
				if (entry.ContentType == ClipboardContentType.File)
					File.Delete(Server.MapPath(((FileClipboardContent)entry).File));
			}
			
			return result.Take(MAX_ENTRIES);
		}
		catch (Exception ex)
		{
			message.Text = ex.Message; 
		}
		finally
		{
			try { sr.Close(); } catch {}
		}

		return sl.Values;
    } 
}